Python 中的 typing 使用
Python 中的 typing 使用
主要是概括 pep-0484 的对 python 中类型检查的使用。pep-3107 中开始提出引入元信息对 python 中的函数(变量)进行注释。类型提示的主要目的是让静态分析工具和类型检查器能够提高代码质量和在运行时之前发现错误。类型提示是可选的,对代码的运行时行为没有影响。注释本身可以在运行时通过__annotations__属性访问获得,但是不会在运行时(runtime)进行类型检查
# 一个简单的注释例子。
def greeting(name: str) -> str:
return 'Hello' + name
动机
提高代码的可读性、可维护性和更健壮的代码,同时也可以让 IDE 正确地对代码进行显示补全(直观点的就是 VS Code 中代码的颜色)
语法
类型别名
使用 TypeVar 自定义类型,或者现有类型进行重命名或组合命名,具体见下方例子:
# 简单赋值重命名
Url = str
def retry(url: Url, retry_count: int) -> None: ...
# 复杂类型,并进行自命名
from typing import TypeVar, Iterable, Tuple
T = TypeVar('T', int, float, complex)
# 这里也可以不重命名为Vector,可以直接使用Iterable[Tuple[T, T]]
Vector = Iterable[Tuple[T, T]]
def inproduct(v: Vector[T]) -> T:
return sum(x*y for x, y in v)
def dilate(v: Vector[T], scale: T) -> Vector[T]:
return ((x * scale, y * scale) for x, y in v)
vec = [] # type: Vector[float]
函数 (callable)
在使用回调函数时为了方便代码 debug 和阅读,可以使用 Callable[[Arg1Type, Arg2Type], ReturnType] 来进行注释。下面给出具体的例子:
from typing import Callable
def feeder(get_next_item: Callable[[], str]) -> None:
# Body
def async_query(on_success: Callable[[int], None],
on_error: Callable[[int, Exception], None]) -> None:
# Body
# 也支持用ellipsis来省略可调用的输入参数类型
def partial(func: Callable[..., str], *args) -> Callable[..., str]: ...
泛型 (generic)
容器中对象的类型信息不能以一种通用方式 (generic way)推理出来。因此通过使用 typing 中的 TypeVar 来定义泛型(Generics),进而表明容器中对象的类型。
from typing import Sequence, TypeVar
T = TypeVar('T')
def first(l: Sequence[T]) -> T:
return l[0]
在泛型的使用中也有以下几点需要注意:
T = TypeVar ('T')
在不指定类型的情况下,此时 T 会自动链接输入的类型
from typing import TypeVar, Text
def identity_int(arg: int) -> int: return arg
def identity_str (arg: str) -> str: return arg
# 上述的代码可以转换为
T = TypeVar("T")
def identity (arg: T) -> T: return arg
# 这里还要注意甄别下 | 类型和 T 的区别
def identity (arg: int | str) -> int | str: return value
# 同时还要注意在 TypeVar 中传入多个类型时,不能混合。以下面的例子,一个输入是另一个输入则必须也是Text
AnyStr = TypeVar ('AnyStr', Text, bytes)
def concat (x: AnyStr, y: AnyStr) -> AnyStr: return x + y
其他泛型注释
- List
- Dict
- set
需要注意的是以上应该都可以通过抽象抽象基类来注释,使用抽象基类时,可以标注出参数类型 - Iterable
- Sequence
- Mapping
其他常用的归纳
typing 中其他常用的类型注释
- Union (Python 3.10 引入了 | 作为快速定义符)
- Optional (Optional[X] 等同于 X | None)
- Any
- NoReturn
类型提示遵循一些通用的规则和约定 :
- 类型提示只在函数参数、返回值、类属性和变量的注解中有效。它们在其他地方无效,比如表达式或语句中。
- 类型提示应该保持简单,避免动态或复杂的表达式,可能会让类型检查器或其他工具感到困惑。
- 类型提示不应该改变代码的语义或行为。它们只应该提供额外的信息,供静态分析或优化使用。
- 类型提示应该与运行时值的实际类型一致。类型检查器应该验证类型提示与表达式的推断类型是否匹配。
- 类型提示应该尊重鸭子类型和结构子类型的原则。它们不应该对传递给函数或赋值给变量的值施加不必要的限制。
- 类型提示应该支持Python代码中常见的习惯和模式,比如多重继承、泛型编程、函数重载等